package com.beerandjesus.test.suite.testng;

import java.io.*;
import java.util.*;

import org.apache.commons.cli.*;
import org.testng.xml.*;

/**
 * A command-line Java application that creates a TestNG test suite
 * file containing all classes under <code>src/test/java</code> in
 * the current project that end in "Test.java".
 * <p>
 * The file is written here: <code>test-output/testng.xml</code>
 * </p><p>
 * Run this program with argument "help" to see options.
 * </p>
 * @author mstevens
 *
 */
public class AllTestsSuiteGenerator {
	
	private List<XmlClass> classes = new ArrayList<XmlClass>();
	
	private static String SKIP_PATTERN = ".svn";
	
	private boolean verbose = false;
	
	public void setVerbose(boolean verbose) {
		this.verbose = verbose;
	}

	public static void main(String[] args) throws IOException, ParseException {
		// Process command line arguments
		Option help = new Option("help", "print this message");
		Option excludedGroups = new Option("excludedGroups", "include all test groups except those specified (comma delimited list, no spaces)");
        excludedGroups.setValueSeparator(',');
        Option includedGroups = new Option("includedGroups", "include only tests of the specified groups (comma delimited list, no spaces)");
        includedGroups.setValueSeparator(',');
        Option verbose = new Option("verbose", "verbose output");
		Options options = new Options().addOption(help).addOption(excludedGroups).addOption(includedGroups).addOption(verbose);
		CommandLineParser parser = new GnuParser();
		CommandLine commandLine = parser.parse(options, args);
		if (commandLine.hasOption("help")) {
			HelpFormatter formatter = new HelpFormatter();
			formatter.printHelp("java AllTestsSuiteGenerator", options);
			return;
		}
        List<String> exGroups = new ArrayList<String>();
        List<String> inGroups = new ArrayList<String>();
        if (commandLine.hasOption("includedGroups")) {
            inGroups = Arrays.asList(includedGroups.getValues());
            System.out.println("Including groups: " + inGroups.toString());
        } else if (commandLine.hasOption("excludedGroups")) {
            exGroups = Arrays.asList(excludedGroups.getValues());
            System.out.println("Excluding groups: " + exGroups.toString());
        }
		AllTestsSuiteGenerator gen = new AllTestsSuiteGenerator();
		if (commandLine.hasOption("verbose")) {
			gen.setVerbose(true);
		}
		gen.writeSuiteFile(exGroups, inGroups);
		System.out.println("DONE");
	}

	private void writeSuiteFile(List<String> excludedGroups, List<String> includedGroups) throws IOException {
		File file = new File("./src/test/java");
		
		stepIn(file);
		
		XmlSuite suite = new XmlSuite();
		XmlTest test = new XmlTest(suite);
		test.setName("All Tests");
		test.setXmlClasses(classes);
		
		List<String> groups = new ArrayList<String>();
        if (includedGroups.size() > 0) {
            for (String group : includedGroups) {
                groups.add(group);
            }
            test.setIncludedGroups(groups);
        } else if (excludedGroups.size() > 0) {
            for (String group : excludedGroups) {
                groups.add(group);
            }
            test.setExcludedGroups(groups);
        }
		File directory = new File("./test-output");
		File xmlFile = new File(directory, "testng.xml");
		directory.mkdir();
		xmlFile.createNewFile();
		FileWriter writer = new FileWriter(xmlFile);
		writer.write(suite.toXml());
		writer.flush();
		writer.close();
		if (verbose) {
			System.out.println("Test suite file: " + xmlFile.getCanonicalPath());
		}
	}

	private void stepIn(File file) {
		if (file.getName().equals(SKIP_PATTERN)) return;
		
		if (file.list() != null) {
			for (String fileName : file.list()) {
				File fileInList = new File(file.getPath(), fileName);
				if (fileInList.isDirectory()) {
					stepIn(fileInList);
				}
				if (fileInList.isFile()) {
					if (fileInList.getPath().endsWith("Test.java")) {
						String path = fileInList.getPath();
						path = path.substring(0, path.indexOf(".java"));
						path = path.substring(path.indexOf("java") + 5, path.length());
						path = path.replace('/', '.');
						path = path.replace('\\', '.');
						XmlClass xmlClass = new XmlClass(path);
						classes.add(xmlClass);
					}
				}
					
				
			}
		}
		
	}


}
